package edu.eas.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import edu.eas.admin.mapper.AdminMapper;
import edu.eas.admin.mapper.RoleMenuMapper;
import edu.eas.admin.mapper.UserRoleMapper;
import edu.eas.admin.service.*;
import edu.eas.common.api.CommonResult;
import edu.eas.common.api.ResultCode;
import edu.eas.common.constant.AuthConstant;
import edu.eas.common.constant.Constants;
import edu.eas.common.domain.UserDto;
import edu.eas.common.dto.AdminParam;
import edu.eas.common.dto.MenuNode;
import edu.eas.common.exception.ApiException;
import edu.eas.common.exception.Asserts;
import edu.eas.common.pojo.Admin;
import edu.eas.common.pojo.Role;
import edu.eas.common.pojo.UserRole;
import edu.eas.common.utils.ServletUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author cql
 */
@Service
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private RoleService roleService;

    @Autowired
    private AuthService authService;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private MenuService menuService;

    @Autowired
    private UserRoleMapper userRoleMapper;

    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();


    @Override
    public CommonResult login(String username, String password) {
        if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
            Asserts.fail("用户名或密码不能为空！");
        }
        Map<String, String> params = new HashMap<>();
        params.put("client_id", AuthConstant.ADMIN_CLIENT_ID);
        params.put("client_secret", "123456");
        params.put("grant_type", "password");
        params.put("username", username);
        params.put("password", password);
        params.put("user_type", AuthConstant.USER_TYPE_ADMIN.toString());
        CommonResult restResult = authService.getAccessToken(params);
        if (ResultCode.SUCCESS.getCode() == restResult.getCode() && restResult.getData() != null) {
            // TODO 如果成功,记录登录用户信息
        }
        return restResult;
    }

    @Override
    public Admin getCurrentAdmin() {
        String userStr = ServletUtils.getRequest().getHeader(AuthConstant.USER_TOKEN_HEADER);
        if (StrUtil.isEmpty(userStr)) {
            Asserts.fail(ResultCode.UNAUTHORIZED);
        }
        UserDto userDto = JSONUtil.toBean(userStr, UserDto.class);
        Admin admin = adminMapper.selectByPrimaryKey(userDto.getId());
        return admin;
    }

    @Override
    public List<Admin> list(Integer pageSize, Integer pageNum, String username, Integer status) {
        PageHelper.startPage(pageNum, pageSize);
        return adminMapper.list(username, status);
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public int create(AdminParam param) {
        // 1.判断用户账号是否存在
        Admin temp = adminMapper.selectByUsername(param.getUsername());
        if (temp != null) {
            throw new ApiException("账号" + temp.getUsername() + "已存在");
        } else {
            temp = new Admin();
            BeanUtils.copyProperties(param, temp);

            Admin admin = this.getCurrentAdmin();
            Date now = new Date();
            temp.setCreateBy(admin.getAdminId());
            temp.setCreateTime(now);
            temp.setUpdateBy(admin.getAdminId());
            temp.setUpdateTime(now);
            temp.setLoginTime(now);
            temp.setPassword(passwordEncoder.encode(temp.getPassword()));
            // 2.基本信息
            int rows = adminMapper.insert(temp);
            // 3.角色关联
            if (param.getRoleIds() != null) {
                List<UserRole> userRoles = new ArrayList<>();
                for (Long id : param.getRoleIds()) {
                    UserRole u = new UserRole(temp.getAdminId(), id, AuthConstant.USER_TYPE_ADMIN);
                    userRoles.add(u);
                }
                userRoleMapper.batchInsert(userRoles);
            }
            return rows;
        }
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public int update(Long adminId, AdminParam param) {
        // 1.检查账号是否重复
        Admin temp = this.getAdminByUsername(param.getUsername());
        if (temp != null && !temp.getAdminId().equals(adminId)) {
            throw new ApiException("账号" + temp.getUsername() + "已存在");
        } else {
            temp = new Admin();
            BeanUtils.copyProperties(param, temp);
            Admin admin = this.getCurrentAdmin();
            temp.setAdminId(adminId);
            temp.setUpdateTime(new Date());
            temp.setUpdateBy(admin.getAdminId());
            // 1.修改基本信息
            int rows = adminMapper.update(temp);
            // 2.删除角色关联
            userRoleMapper.deleteByUserId(adminId, AuthConstant.USER_TYPE_ADMIN);
            // 3.新的关联
            if (param.getRoleIds() != null) {
                List<UserRole> userRoles = new ArrayList<>();
                for (Long id : param.getRoleIds()) {
                    UserRole u = new UserRole(adminId, id, AuthConstant.USER_TYPE_ADMIN);
                    userRoles.add(u);
                }
                userRoleMapper.batchInsert(userRoles);
            }
            return rows;
        }
    }

    @Override
    public Admin getAdminByPrimaryKey(Long adminId) {
        return adminMapper.selectByPrimaryKey(adminId);
    }

    @Override
    public int changeStatus(Admin admin) {
        Admin cur = getCurrentAdmin();
        admin.setUpdateBy(cur.getAdminId());
        admin.setUpdateTime(new Date());
        return adminMapper.update(admin);
    }

    @Override
    public int deleteAdminByIds(Long[] adminIds) {
        for (Long adminId : adminIds) {
            if (adminId.equals(1L)) {
                throw new ApiException("不允许操作超级管理员用户");
            }
        }
        userRoleMapper.deleteUserRole(adminIds, AuthConstant.USER_TYPE_ADMIN);
        return adminMapper.deleteAdminByIds(adminIds);
    }

    @Override
    public int resetPwd(Admin admin) {
        Admin temp = getCurrentAdmin();
        admin.setPassword(passwordEncoder.encode(admin.getPassword()));
        admin.setUpdateBy(temp.getAdminId());
        temp.setUpdateTime(new Date());
        return adminMapper.update(admin);
    }

    @Override
    public List<MenuNode> selectMenuTree(Long adminId) {
        List<MenuNode> result = null;

        // 如果是超级管理员,则获取所有的菜单树
        if (adminId.equals(1L)) {
            result = menuService.selectMenuTreeAll();
        } else {
            result = menuService.selectMenuTreeByAdminId(adminId);
        }
        return result;
    }


    @Override
    public UserDto loadUserByUsername(String username) {
        // 1.获取用户基本信息
        Admin admin = getAdminByUsername(username);
        if (admin != null) {
            UserDto userDTO = new UserDto();
            userDTO.setUsername(admin.getUsername());
            userDTO.setId(admin.getAdminId());
            BeanUtils.copyProperties(admin, userDTO);
            // 2.获取用户角色
            List<Role> roleList = getRoleList(admin.getAdminId());
            if (CollUtil.isNotEmpty(roleList)) {
                List<String> roleStrList = roleList.stream().map(item -> item.getRoleId() + "_" + item.getRoleKey()).collect(Collectors.toList());
                userDTO.setRoles(roleStrList);
            }
            // 3.设置用户类型
            userDTO.setUserType(AuthConstant.USER_TYPE_ADMIN);
            return userDTO;
        }
        return null;
    }

    @Override
    public Admin getAdminByUsername(String username) {
        return adminMapper.selectByUsername(username);
    }

    @Override
    public List<Role> getRoleList(Long adminId) {
        return roleService.getRoleList(adminId, AuthConstant.USER_TYPE_ADMIN);
    }

}
